package network;

import java.io.IOException;
import java.util.ArrayList;

import core.Phrox;
import core.Util;

public class DisconnectThread implements Runnable {

	private Object lock = new Object();//use this object as a lock
	private volatile boolean running = false;//don't access this without using a synchronized block on 'lock'

	private ArrayList<Connection> cons = new ArrayList<Connection>();//make sure that use of this list is synchronized
	//this list holds the connections that must be sent redund info, and then closed

	private Peer p = null;//this is the peer we connect to, we only need this to get redund lists
	
	public DisconnectThread(Peer p){
		this.p = p;
		//after creating this, make sure that it gets started
	}
	
	public void run(){

		synchronized(lock){
			if( running ){
				return;
			} else {
				running = true;
			}
		}

		//actual code goes here
		
		/*
		Idea:
			Synchronize on connection list, grab first != null connection. Remove from array
			unsync on array (this will make it very easy to add to the list)
				(if we don't do this then we can't add connections easily, and the add connection will time out
					(this is very bad.) )

		*/
		
		while( !Phrox.exit ){
			
			Connection c = null;
			
			synchronized(cons){
				for(int i=0; i<cons.size(); i++){
					if(cons.get(i) != null){
						c = cons.get(i);
						cons.remove(i);
					}
				}
				cons.notify();//required for the addConnection to go through it's cons.wait(...) quickly
				
				if(c == null){
					try {
						Thread.sleep(500);//TODO: Modify time out?
					} catch (InterruptedException e) {/* Don't really need to worry about this */}
					continue;
				}
				
				//now c != null, we have the connection to close
				
				Message m = new Message(Message.S_REDUND, Util.flatten(p.getRedund()) );
				try {
					NetIO.write(c, m);//send S_Redund, then disconnect
					NetIO.disconnect(c);//if this throws IOException, we just don't care. force close connection
					
				} catch (IOException e) {
					System.out.println("IO Exception while trying to send S_Redund.");
					try {
						//force close, don't care if they don't get what we were sending... :( too bad
						NetIO.dropConnection(c);
					} catch (DisconnectionException e1) {
						//doesn't matter. we're disconnecting any way.
					}
				} catch (DisconnectionException e) {
					System.out.println("Connection exited while trying to send S_Redund.");
					//don't care about this, doesn't matter, makes life easy.
				}
			}
			
		}//end of while loop on phrox.exit
		
		synchronized(lock){
			running = false;
		}

	}

	public void addConnection(Connection c){
		try {
			cons.wait(100);//had this at 1second, seemed too long. could cause problems. This has to happen fast.
			synchronized(cons){
				if( !cons.contains(c) ){
					cons.add(c);
					//this should happen relatively quickly, so we should be able to release
					// cons elsewhere (run method) for brief moments once and a while.
				}
			}
		} catch (InterruptedException e) {
			//don't know what caused this, print stack trace, and try again.
			e.printStackTrace(System.out);
			this.addConnection(c);
		}
	}


}
